
local assert     = assert
local require    = require
local bit        = bit
local coroutine  = coroutine
local debug      = debug
local io         = io
local pairs      = pairs
local ipairs     = ipairs
local math       = math
local os         = os
local print      = print
local pcall      = pcall
local xpcall     = xpcall
local rawget     = rawget
local rawset     = rawset
local select     = select
local string     = string
local table      = table
local tonumber   = tonumber
local tostring	 = tostring
local error      = error
local type       = type
local unpack     = unpack
local setmetatable = setmetatable
local getmetatable = getmetatable
local ngx = ngx
local next = next

local string_char  = string.char
local string_sub   = string.sub
local string_byte  = string.byte
local string_gsub  = string.gsub
local string_find  = string.find
local string_upper = string.upper
local string_lower = string.lower

local math_fmod   = math.fmod
local math_floor  = math.floor
local math_pow    = math.pow
local math_abs    = math.abs

----数据变量----
local uu         = require("modules.commhm.utils");
local log        = require("modules.commhm.log");
local ns_time    = require("modules.commhm.time");
local ns_network = require("modules.commhm.network");
local ns_config  = require("modules.center_server.center_config")

local CNgxTimerWrap   = require("modules.commhm.ngxTimerWrap" )

local table_insert = table.insert
local table_concat = table.concat
local table_sort   = table.sort

local table_tostring = table.tostring
local table_loadstring = table.loadstring



local FOO = {
	_VERSION = '0.12.1',

	worker_id = ngx.worker.id(),

	report_cal_data = {},      --- 上报的统计值
};


---默认需要更新的目录
FOO.limit_default_dir = {
	tools = 1,
	base = 2,
	common = 2,
}

---不能更新的目录
FOO.ignored_update_dir = {
	[ "modules/env/" ] = 1,
	[ "modules/env" ]  = 1,
	[ "modules/" ]     = 1,
	[ "modules" ]      = 1,
	[ "lua/" ]         = 1,
	[ "lua" ]          = 1,
}


local gg = FOO;   --这里也可以调用gg


FOO.init = function()
	FOO.timer_every( 30, FOO.calAllLoad )
end


-- 正常退出
FOO.final = function()
end



---延迟执行一个任务
FOO.timer_at = function( delay_, func_, params_ )
	local timer_ = CNgxTimerWrap:new()
	return timer_:ngx_timer_at( delay_, func_,  params_ )
end


---定期执行一个任务
FOO.timer_every = function( delay_, func_, params_ )
	local timer_ = CNgxTimerWrap:new()
	return timer_:ngx_timer_every( delay_, func_, params_  )
end


------------------------------------------------------
---按格式返回 lua table or json
FOO.return_table = function( t )
	t = t or {};

	if  type(t) ~= 'table' then
		t = { ret=t };
	end

	if  ngx.ctx.m_params.json == '1' then
		--json ajax 跨域
		ngx.header["Access-Control-Allow-Origin"] = "*";
		ngx.header["Server"] = "php";

		--log.debug("return json");
		local jret = uu.table2json( t );
		ngx.say(jret);

	elseif ngx.ctx.m_params.log == '1' then
		--log
		log.debug( "<br><br>=========================return begin========" );
		uu.var_dump(t)
		log.debug( "=========================return end========<br><br>" );

	else
		--lua
		local ret = table_tostring( t );
		ngx.say( ret);
	end
end


--返回一个是否是json的后缀
FOO.get_json_postfix = function()
	if  ngx.ctx.m_params.json and ngx.ctx.m_params.json == '1' then
		return "_json"
	else
		return ""
	end
end



-- 配置文件改动
function FOO.cb_refresh_servers_update( content_ )
	log.day_list( "center_server", "cb_refresh_servers_update", "begin_call" )
	local config_ = table.loadstring( content_ )
	if  type(config_) == 'table' then

		if  config_.data then
			log.day_list( "center_server", "cb_refresh_servers_update:data", uu.to_str(config_.data) )
		end

		if  config_.dc_gate_config then
			-- dc_gate的补充路由
			log.day_list( "center_server", "cb_refresh_servers_update:dc_gate_config", uu.to_str(config_.dc_gate_config) )
			if  FOO.worker_id == 0 then
				for dc_name_, v in pairs( config_.dc_gate_config ) do
					if  type(v) == 'table' then
						for name_, config_ in pairs(v) do
							if  type(config_) == 'table' and config_.server and config_.select then

								--0_map_dc2.lua
								local key_ = ns_config.debug .. '_' .. name_ .. '_' .. dc_name_
								local post_value_ = table.tostring( config_ )

								--检查是否有变化
								local m_ = uu.get_server_cache_string( 0, key_ )
								if  m_ and m_ == post_value_ then
									log.day_list( "center_server", "un_change_shared_by_LuaConfig", key_ )
								else
									--文件是否有变化
									local file_name_ = ns_config.center_lua_config_dir_root .. 'dc_client_config/' .. key_ .. '.lua'
									local content_ = uu.read_file_content_safe( file_name_ )
									if  content_ == post_value_ then
										log.day_list( "center_server", "un_change_file_by_LuaConfig", key_ )
										uu.set_server_cache_string( 0, key_, post_value_, 86400 )
									else
										uu.set_server_cache_string( 0, key_, post_value_, 86400 )
										uu.write_file_content( file_name_, post_value_ )
										log.day_list( "center_server", "change_file_by_LuaConfig", key_, "save_file_ok" )
									end

								end
							end
						end
					end
				end
			end
		end

	else
		log.day_list( "center_server", "cb_refresh_servers_update", "empty" )
	end
end


---读git中一共有哪些模块可以更新(过滤限制)
function FOO.load_lua_modules_dict_limit()

	local limit_ = uu.table_value_copy( FOO.limit_default_dir )
	local dict_ = uu.table_value_copy( FOO.ignored_update_dir )

	local function scan_dir_( dir_, type_ )
		---扫描目录
		local dir_scan_str_ = uu.os_exec(  'cd ' .. dir_ .. '; find ./lua/modules/ -maxdepth 1 -type d | sort' )
		local t_ = uu.split( dir_scan_str_, '\n' )
		for k, v in pairs(t_) do
			if  v and #v > 1 then
				local line_ = uu.trim( v )
				--- ./lua/modules/monitor
				--- ./lua/modules/mult_lang_map
				--- ./lua/modules/mysql_tables
				if  string.sub( line_, 1, 14 ) == './lua/modules/' then
					local dir_ = string.sub( line_, 7 )
					if  #dir_ > 1 and (not dict_[ dir_ ]) then
						--ret_[ #ret_ + 1 ] = dir_
						limit_[ dir_ ] = type_
						dict_[ dir_ ] = type_
					end
				end
			end
		end
	end

	--/home/samba/haima/code/miniw_activity/env1/
	--/home/samba/haima/code/miniw_room/
	scan_dir_( '/home/samba/haima/code/miniw_activity/env1/', 1 )   --miniw_activity
	scan_dir_( '/home/samba/haima/code/miniw_room/', 2 )            --miniw_room

	log.debug( "===================limit=====================" )
	uu.var_dump( limit_ )
	return limit_
end



-----------------------------------
---各服务上报一个load值,上报负载使用,已接入ma_gate,dc_gate,data_cache
function FOO.reportLoad()

	--server_name = server_name_,
	--load_name = load_name_,
	--load      = load_,
	--env = ns_env.debug,
	--worker_id = ngx.worker.id(),
	--ver_lua
	--ver_hot

	local pp_ = ngx.ctx.m_params

	if  not pp_.load_name then
		log.day_list( "center_server_load", "error_save_no_load_name", uu.to_str( pp_ ) )
		gg.return_table( { ret=1, msg="error_save_no_load_name" } )
		return
	end

	local key_ =  pp_.load_name .. "_" .. pp_.env .. "_" .. (ngx.var.remote_addr or "no_ip")
	if  pp_.sub_type then
		key_ = key_ .. '_' .. pp_.sub_type
	end

	local t_ = {
		load  = tonumber( pp_.load  ) or 0,
		env = pp_.env,
		ver_lua = pp_.ver_lua,
		ver_hot = pp_.ver_hot,
		ip = (ngx.var.remote_addr or "no_ip"),
		sub_type = pp_.sub_type,
		rt = uu.now(),   --report_time
	}
	if  pp_.load1 then	t_.load1 = tonumber( pp_.load1  ) or 0	end
	--if  pp_.load2 then  t_.load2 = tonumber( pp_.load2  ) or 0	end   --暂无业务用到


	if  pp_.post_data == '1' then
		ngx.req.read_body()
		t_.post_data = ngx.req.get_body_data()
		--log.day_list( "center_server_load", "read_post_json_data", key_, uu.to_str(t_.post_data) )
	end


	local value_ = table.tostring( t_ )

	--- 两块逻辑分开写，可能会有特别的逻辑
	if  pp_.load_name == "ma_gate" then
		---目前load值都是每30秒上报一次，calAllLoad会将值累加起来
		ngx.shared.ma_gate_list:set( key_, value_, 86400 )
	elseif 	pp_.load_name == "data_cache" then
		ngx.shared.data_cache_list:set( key_, value_, 86400 )
	elseif 	pp_.load_name == "dc_gate" then
		ngx.shared.dc_gate_list:set( key_, value_, 86400 )
	else
		log.day_list( "center_server_load", "save_error", pp_.server_name, uu.to_str( pp_ ) )
		gg.return_table( { ret=1, msg="save_error" } )
		return
	end

	log.day_list( "center_server_load", "save", pp_.server_name, key_,
			pp_.load, pp_.load1, pp_.ver_lua, pp_.ver_hot )
	gg.return_table( { ret=0 } )
end



---计算上报值( 按上报的值，计算每个环境的网关总调用量 )
function FOO.calAllLoad()
	FOO.calAllLoadByName( ngx.shared.ma_gate_list,    "ma_gate"    )
	FOO.calAllLoadByName( ngx.shared.data_cache_list, "data_cache" )
end



----每30秒上报量用来计算指标的值
FOO.ma_gate_load_config = {
	['0']  = 30 * 80000,   --- 240w (国内正式)
	['1']  = 30 * 100,
	['2']  = 30 * 100,

	['10'] = 30 * 30000,   ---  90w (海外正式)
	['11'] = 30 * 100,
	['12'] = 30 * 100,
}



---按指定名字计算
function FOO.calAllLoadByName( dict_, load_name_ )
	local all_report_  = dict_:get_keys(1024)

	local detail_ = {}     --index日志
	local log_call_ = {}   --打印调用日志

	---计算上报的详情（将所有值累加起来）(30秒上报的平均值)(每一个work都计算)
	for index_, key_ in pairs(all_report_) do
		local str_ = dict_:get(key_)

		--if  FOO.worker_id == 0 then
		--log.day_list( "center_server_load", "read", load_name_, index_, key_, str_ )
		--end

		local remote_ip_

		local k_ = table.loadstring( str_ )
		if  type(k_) == 'table' and k_.env then
			local env_ = k_.env

			if  not detail_[ env_ ] then detail_[ env_ ] = {} end
			detail_[ env_ ].load  = (detail_[ env_ ].load  or 0) + k_.load

			if  k_.load1 then
				detail_[ env_ ].load1 = (detail_[ env_ ].load1 or 0) + k_.load1
			end

			if  k_.load2 then
				detail_[ env_ ].load2 = (detail_[ env_ ].load2 or 0) + k_.load2
			end

			if  k_.ip then
				remote_ip_ = k_.ip
			end

			---如果有ma_gate, 计算 load_index 指标值 ( 0到100， 大于100则负载过大 )
			if  load_name_ == 'ma_gate' then
				local load_index_ = FOO.ma_gate_load_config[ env_ ]
				if  load_index_ then
					detail_[ env_ ].load_index = math.floor( (detail_[ env_ ].load / load_index_) * 100 )
				end
			end


			-- log_call_  计算命令的调用次数 post ma_gate特有
			if  FOO.worker_id == 0 then
				--{["call"]=32,["to"]="/miniw/map@120.24.64.132:8079",["code"]="report_event",["from"]="ma_gate",["cost"]=58}
				if  k_.post_data then
					local json_table_ = uu.json2table( k_.post_data )
					if  type(json_table_) == 'table' then
						for num_, t_ in pairs(json_table_) do

							if  load_name_ == 'ma_gate' then
								--合并调用次数
								if  type(t_) == 'table' and t_.to and t_.code then
									if  not log_call_[env_]                 then log_call_[env_] = {} end
									if  not log_call_[env_][t_.to]          then log_call_[env_][t_.to] = {} end
									if  not log_call_[env_][t_.to][t_.code] then log_call_[env_][t_.to][t_.code] = { call=0, cost=0, type=1 } end

									if  not log_call_[env_]['all']          then log_call_[env_]['all'] = {} end
									if  not log_call_[env_]['all'][t_.code] then log_call_[env_]['all'][t_.code] = { call=0, cost=0, type=2 } end

									log_call_[env_][t_.to][t_.code].call = log_call_[env_][t_.to][t_.code].call + t_.call
									log_call_[env_][t_.to][t_.code].cost = log_call_[env_][t_.to][t_.code].cost + t_.cost

									log_call_[env_]['all'][t_.code].call = log_call_[env_]['all'][t_.code].call + t_.call
									log_call_[env_]['all'][t_.code].cost = log_call_[env_]['all'][t_.code].cost + t_.cost
								end
							elseif load_name_ == 'data_cache' then
								--from name cmd c b
								--合并调用次数
								if  type(t_) == 'table' and t_.name and t_.cmd then

									local from_ = t_.name .. '@' .. t_.from
									if  remote_ip_ then
										from_ = from_ .. '(' .. remote_ip_ ..')'
									end

									if  not log_call_[env_]                then log_call_[env_] = {} end
									if  not log_call_[env_][from_]         then log_call_[env_][from_] = {} end
									if  not log_call_[env_][from_][t_.cmd] then log_call_[env_][from_][t_.cmd] = { c=0, b=0, type=1 } end

									log_call_[env_][from_][t_.cmd].c = log_call_[env_][from_][t_.cmd].c + t_.c
									log_call_[env_][from_][t_.cmd].b = log_call_[env_][from_][t_.cmd].b + t_.b

									if  not log_call_[env_][t_.name]         then log_call_[env_][t_.name] = {} end
									if  not log_call_[env_][t_.name][t_.cmd] then log_call_[env_][t_.name][t_.cmd] = { c=0, b=0, type=2 } end

									log_call_[env_][t_.name][t_.cmd].c = log_call_[env_][t_.name][t_.cmd].c + t_.c
									log_call_[env_][t_.name][t_.cmd].b = log_call_[env_][t_.name][t_.cmd].b + t_.b

								end
							else

							end

						end
					end
				end
			end

		end
	end


	local print_list_ = {}
	-- 打印统计调用日志
	if  FOO.worker_id == 0 then
		for env_, v in pairs(log_call_) do
			for to_, m in pairs( v ) do
				for code_, info_ in pairs( m ) do
					--call cost
					local tmp_
					if  load_name_ == 'ma_gate' then
						tmp_ = {
							env  = env_,
							type = info_.type,
							cc   = info_.call,
							txt = table_concat( { 'e' .. env_, load_name_,
												  'a=' .. math_floor(info_.call/30),
												  't=' .. math_floor(info_.cost/info_.call),
												  'a=' .. info_.call .. '/' .. 30,
												  't=' .. info_.cost .. '/' .. info_.call,
												  to_, code_ }, '|' ),
						}
					elseif load_name_ == 'data_cache' then
						tmp_ = {
							env  = env_,
							type = info_.type,
							cc   = info_.c,
							txt = table_concat( { 'e' .. env_, load_name_,
												  'a=' .. math_floor(info_.c/30),
												  'b=' .. math_floor(info_.b/info_.c),
												  'a=' .. info_.c .. '/' .. 30,
												  'b=' .. info_.b .. '/' .. info_.c,
												  to_, code_ }, '|' ),
						}
					else
						tmp_ = { env=env_, type=99, cc=0, txt='unknown' }
					end

					if  ( env_=='0' or env_=='10' )	then
						if  tmp_.cc >= 500 then
							print_list_[#print_list_+1] = tmp_
						end
					elseif  tmp_.cc >= 10 then
						print_list_[#print_list_+1] = tmp_
					else
						--filter
					end
				end
			end
		end


		print_list_[#print_list_+1] = { type=0, env='0', cc=0, txt='e0|  ---------- ' .. load_name_ }
		print_list_[#print_list_+1] = { type=0, env='1', cc=0, txt='e1|  ---------- ' .. load_name_ }
		print_list_[#print_list_+1] = { type=0, env='2', cc=0, txt='e2|  ---------- ' .. load_name_ }

		--print_list_[#print_list_+1] = { type=0, env='10', cc=0, txt='----------' }
		--print_list_[#print_list_+1] = { type=0, env='11', cc=0, txt='----------' }
		--print_list_[#print_list_+1] = { type=0, env='12', cc=0, txt='----------' }

		---按call env cc值排序打印
		local function sort_func_( a_, b_ )
			if  a_.env ~= b_.env then
				return a_.env < b_.env
			end
			if  a_.type ~= b_.type then
				return a_.type < b_.type
			end
			return a_.cc < b_.cc
		end
		table_sort( print_list_, sort_func_ )

		for i=1, #print_list_ do
			log.day_list( "center_server_load", 'tj', print_list_[i].txt )
		end

	end


	-- 打印load_index日志，并上报到fatal
	if  FOO.worker_id == 0 then
		log.day_list( "center_server_load", "detail", load_name_, FOO.worker_id, uu.to_str( detail_ ) )
		for env_, v in pairs(detail_) do
			if  v.load and v.load > 0 then
				local load_ave_ = math.floor(v.load / 30)
				log.day_list( "center_server_load", "load_index", load_name_, env_,
						v.load, load_ave_, v.load_index )

				-- level    严重程度  0fatal > 1error > 2warn > 3info
				-- env      环境
				-- key      唯一排重key
				-- tt       时间间隔   ( n秒内被排重掉 )
				-- value    字符串( post里 )
				-- ip       需要分ip上报

				local args_ = {
					level = 3,
					env = env_,
					key = 'load_' .. load_name_,
					tt  = 600,    -- 10分钟排重
				}

				local ext_string_ = ''
				if  load_name_ == 'ma_gate' and v.load_index then
					ext_string_ = ',index=' .. v.load_index
				end

				FOO.write_fatalReport( args_, 'tps='..load_ave_..',load='.. v.load .. ext_string_ )

			end
		end



	end


	---设置到全局变量中，等待其他服务查询
	FOO.report_cal_data[load_name_] = detail_

end





---获得指定名字的load值，目前只有网关上报负载使用
function FOO.getLoadByName()
	local fret_ = {}
	local pp_ = ngx.ctx.m_params
	local load_name_ = pp_.load_name
	local load_env_  = pp_.env

	uu.var_dump( FOO.report_cal_data )

	if  load_name_ then
		---指定了名字
		if  FOO.report_cal_data[ load_name_ ] and FOO.report_cal_data[ load_name_ ][ load_env_ ] then
			fret_[ load_name_ ] = FOO.report_cal_data[ load_name_ ][ load_env_ ]
		end
	else
		---未指定名字返回 ma_gate 和 data_cache 的 load
		if  FOO.report_cal_data.ma_gate and FOO.report_cal_data.ma_gate[ load_env_ ] then
			fret_.ma_gate    = FOO.report_cal_data.ma_gate[ load_env_ ]
		end

		if  FOO.report_cal_data.data_cache and FOO.report_cal_data.data_cache[ load_env_ ] then
			fret_.data_cache = FOO.report_cal_data.data_cache[ load_env_ ]
		end
	end

	gg.return_table( fret_ )
end


-- 写入关键错误日志
function FOO.write_fatalReport( args_, post_value_ )

	if  not (args_.key and args_.env and args_.level and post_value_ ) then
		log.day_list( 'rp', 'error_params', uu.to_str( args_ ), post_value_ )
		return 'error_params'
	end

	--排重key
	local cache_key_ = args_.key .. '_e' .. args_.env
	if  args_.ip == '1' or args_.ip == 1 then
		cache_key_ = cache_key_ .. '@' .. ngx.var.remote_addr
	end

	-- 重复上报 时间排重
	local ret_ = uu.get_server_cache_string( 0, cache_key_ )
	if  ret_ then
		log.day_list_simple( 'rp', 'ignore', args_.env, args_.level, cache_key_ )
		return 'ignore'
	end

	-- 纠正日志等级
	args_.level = tonumber( args_.level )
	if  args_.level < 0 or args_.level > 3 then
		args_.level = 3
	end

	local tt_ = 10
	if  args_.tt then
		tt_ = tonumber( args_.tt ) or 10
		if  tt_ > 3600 then
			tt_ = 3600
		end
	end
	uu.set_server_cache_string( 0, cache_key_, 1, tt_ )

	-- print log
	local file_name_ = table.concat( { 'rp', 'e'..args_.env, args_.level }, '_' )
	log.day_list_simple( file_name_, args_.level, cache_key_, post_value_ )

	return 'ok'
end



-- 通用上报接口，目前主要给data_cache使用
function FOO.reportDataComm()
	local args_ = ngx.ctx.m_params
	if  args_.action == 'dc_client_config' then
		FOO.comm_dc_client_config( args_ )
	elseif  args_.action == 'get_dc_config' then
		FOO.comm_get_dc_config( args_ )
	else
		log.error("unknown action:" .. uu.to_str( args_.action ) )
	end
end



--------------------------
-- dc_client客户端使用时期上报 ( dc_gate 和 php版本运维工具使用 )
-- env=0 key=map_dc2
-- map = { server={}, select={} }
function FOO.comm_dc_client_config( args_ )
	local key_ =  args_.env .. '_' .. args_.key    --1_map_dc2
	if  not uu.check_server_time_interval( key_, 10 ) then
		log.day_list( "dc_client_config", "time_interval_10", key_ )
		gg.return_table( { ret=0, msg='time_interval_10' } )
		return
	end

	ngx.req.read_body();
	local post_value_ = ngx.req.get_body_data();

	-- 解析url http://10.135.159.88:8055/dc2/?auth=Xcn67K&name=map
	local dc_name_, name_ = FOO.decode_dc_server_url( post_value_ )
	if  dc_name_ and name_ then
		--log.day_list( "dc_client_config", "decode_url", dc_name_, name_ )
		key_ = args_.env .. '_' .. name_ .. '_' .. dc_name_     --1_map_dc2
	else
		log.day_list( "dc_client_config", "fail_decode_url", key_, post_value_ )
		gg.return_table( { ret=99, msg='fail_decode_url' } )
		return
	end

	--检查是否有变化
	local m_ = uu.get_server_cache_string( 0, key_ )
	if  m_ and m_ == post_value_ then
		log.day_list( "dc_client_config", "un_change_shared", key_ )
		gg.return_table( { ret=0, msg='un_change_shared' } )
		return
	end

	--文件是否有变化
	local file_name_ = ns_config.center_lua_config_dir_root .. 'dc_client_config/' .. key_ .. '.lua'
	local content_ = uu.read_file_content_safe( file_name_ )
	if  content_ == post_value_ then
		log.day_list( "dc_client_config", "un_change_file", key_ )
		uu.set_server_cache_string( 0, key_, post_value_, 86400 )
		gg.return_table( { ret=0, msg='un_change_file' } )
		return
	end

	--判断格式
	local config_table_ = table.loadstring( post_value_ )
	if  type( config_table_ ) == 'table' and config_table_.server and config_table_.select then
		log.debug( "check ok" )
	else
		log.day_list( "dc_client_config", "error_content_table", key_, '\n' .. post_value_ )
		gg.return_table( { ret=99, msg='error_content_table' } )
		return
	end

	--保存到share和file
	log.day_list( "dc_client_config", "save_config_file", key_, '\n' .. content_, '\n' .. post_value_ )
	uu.set_server_cache_string( 0, key_, post_value_, 86400 )

	uu.create_dir_if(  ns_config.center_lua_config_dir_root .. 'dc_client_config/' )
	uu.write_file_content( file_name_, post_value_ )

end


-- 获得 dc_client 客户端上报的配置文件 ( dc_gate 和 php版本运维工具使用 )
-- env=0 key=map_dc2
-- map = { server={}, select={} }
function FOO.comm_get_dc_config( args_ )
	local key_ = table.concat( { args_.env, args_.key }, '_' )
	--1 先从shared里拿
	local m1_ = uu.get_server_cache_string( 0, key_ )
	if  m1_ and #m1_>10 then
		ngx.say( m1_ )
		return
	end

	--2 读文件
	local file_name_ = ns_config.center_lua_config_dir_root .. 'dc_client_config/' .. key_ .. '.lua'
	local m2_ = uu.read_file_content_safe( file_name_ )
	if  m2_ and #m2_>10 then
		uu.set_server_cache_string( 0, key_, m2_, 86400 )
		ngx.say( m2_ )
		return
	end

	gg.return_table( { ret=404, msg="not_found" } )
end


-- 从url里解析出 key 和 slant_name
-- url= http://10.135.159.88:8055/dc2/?auth=Xcn67K&name=map   --> dc2 map
function FOO.decode_dc_server_url( post_value_ )

	-- 1 找出url ip和端口可以不同， dc_name和name一定一样
	local url_
	local t_ = table.loadstring( post_value_ )
	if  type(t_) == 'table' and t_.server and t_.select then
		for  k, v in pairs( t_.server ) do
			if  type(v) == 'table' and v.url then
				url_ = v.url
				break
			end
		end
	end

	-- 2 解析出dc_name和name
	local dc_name_, name_      -- dc2 map
	if  url_ then
		local t_ = uu.split( url_, '/' )
		if  type(t_) == 'table' and t_[4] then
			dc_name_ = t_[4]
		end

		local t_ = uu.split( url_, '?' )
		if  type(t_) == 'table' and t_[2] then
			local args_ = ngx.decode_args( t_[2] )
			if  type(args_) == 'table' and args_.name then
				name_ = args_.name
			end
		end
	end

	--1_posting_redis_dc3 ( posting 特殊处理 )
	if  (not name_) and dc_name_ == 'dc3' then
		name_ = 'posting_redis'
	end

	if  dc_name_ and name_ then
		return dc_name_, name_   --同时解析出来才返回
	end

end


return FOO;
